/*******************************************************************************
 *
 *      Filename: Timer.cpp
 *   Description: See Timer.h
 *        Author: [kb]ypp
 *    Created at: November 28, 2005
 * Last modified: November 30, 2005
 *
 ******************************************************************************/

#include "Timer.h"
#include <cassert>

#ifdef _WIN32
#    include <windows.h>
#else
#    include <sys/time.h> // For gettimeofday()
#endif

#ifndef _WIN32

class Timer::TimerImpl {
public:
	void start()
	{
		gettimeofday( &last, 0 );
	}
	
	float delta()
	{
		timeval cur;
		gettimeofday( &cur, 0 );
		float res = ( cur.tv_sec - last.tv_sec ) +
		            0.000001 * ( cur.tv_usec - last.tv_usec );
		last = cur;
		return res;
	}
	
private:
	timeval last;
};

#endif

//! The timer is stopped after construction
//!
Timer::Timer()
	: sec( 0.0 ), last( 0.0 ), running( false ),
	  impl( new TimerImpl )
{
}

Timer::Timer( const Timer &other )
	: sec( other.sec ), last( other.last ), running( other.running ),
	  impl( new TimerImpl )
{
	assert( other.impl );
	*impl = *other.impl;
}

const Timer& Timer::operator=( const Timer &other )
{
	sec = other.sec;
	last = other.last;
	running = other.running;
	assert( impl );
	*impl = *other.impl;
	return *this;
}

Timer::~Timer()
{
	delete impl;
}

void Timer::start()
{
	if ( !running ) {
		assert( impl );
		impl->start();
		running = true;
	}
}

void Timer::stop()
{
	if ( running ) {
		assert( impl );
		sec += impl->delta();
		running = false;
	}
}

//! The timer is stopped after reset()
//!
void Timer::reset()
{
	sec = last = 0.0;
	running = false;
}

float Timer::elapsed() const
{
	if ( running )
		update();
	return sec;
}

float Timer::delta() const
{
	if ( running )
		update();
	float res = sec - last;
	last = sec;
	return res;
}

void Timer::update() const
{
	assert( impl );
	sec += impl->delta();
}
